/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;




/**
 *
 * @author severinefratani
 */
class DotParser extends StreamTokenizer{
	static final int TT_LABEL = -4;  // [number]
	static final int TT_ARROW = -5;  // ->
	static final int TT_SEM = -6;    // ;
	static final int TT_COLOR = -7;
	static final int TT_LBRACE = -8; // {
	static final int TT_RBRACE = -9; // }
	static final int TT_EDGE = -10;  // --
	static final int TT_FLOW = -11;  // nbr1/nbr2

	/** HERITED FROM StreamTokenizer
    static final int TT_WORD = -3;
    static final int TT_NUMBER = -2;
    static final int TT_EOF = -1;

    int ttype;
          After a call to the next method, this field contains the type of the token just read.
    double nval;
          If the current token is a number, (i.e., if ttype == TT_LABEL or, ttype== TT_NUMBER)
          this field contains the value of that number.
    String sval;
          If the current token is a word token, (i.e., if ttype == TT_WORD or ttype=TT_FLOW)
          this field contains a string giving the characters of the word token.
	 **/

	public String toString(){
		String s = new String();
		if (this.ttype==TT_LABEL)
			s=s+ "[label = " +  this.nval + "]";
		else if (this.ttype==TT_ARROW)
			s=s+ " -> ";
		else if (this.ttype==TT_SEM)
			s=s+ " ; ";
		else if (this.ttype==TT_COLOR)
			s=s+ "[color = "+ this.sval + "]";
		else if (this.ttype==TT_LBRACE)
			s=s+ " { ";
		else if (this.ttype==TT_RBRACE)
			s=s+ " } ";
		else if (this.ttype==TT_EDGE)
			s=s+ " -- ";
		else if (this.ttype==TT_FLOW)
			s=s+ " [label = " + this.sval + "]";
		else if (this.ttype==TT_WORD)
			s=s+  this.sval;
		else if (this.ttype==TT_NUMBER)
			s=s+  this.nval ;
		else if (this.ttype==TT_EOF)
			s=s+ " EOF ";
		else s=s+ "unexpected lexem  "+ "'" + (char) this.ttype + "'";
		return s;
	}






	DotParser(String fileName) throws FileNotFoundException{
		super(new FileReader(fileName));
		this.parseNumbers();
		this.ordinaryChar((int)'/');
	}





	int next() throws IOException, DotException{
		this.nextToken();
		if(this.ttype == TT_WORD || this.ttype==TT_NUMBER || this.ttype==TT_EOF);
		else if ((char) this.ttype == '{') this.ttype=TT_LBRACE;
		else if ((char) this.ttype == '}') this.ttype=TT_RBRACE;
		else if ((char) this.ttype == '-'){
			this.nextToken();
			if ((char) this.ttype == '>')
				this.ttype=TT_ARROW;
			else if ((char) this.ttype == '-')
				this.ttype=TT_EDGE;
			else throw  new DotException(this, "> or -");
		}
		else if ((char) this.ttype == ';')

			this.ttype=TT_SEM;
		else if ((char) this.ttype == '['){
			this.nextToken();
			if (this.ttype==TT_WORD && this.sval.equalsIgnoreCase("label")){
				this.nextToken();
				double lab1=0;
				if ((char) this.ttype == '=')
					this.nextToken();
				else throw new DotException(this, "=");
				if (this.ttype==TT_NUMBER){
					lab1 = this.nval;
					this.nextToken();
				}else throw new DotException(this, "number");
				if ((char) this.ttype == ']'){
					this.ttype = TT_LABEL;
					this.nval = lab1;
				}else if ((char) this.ttype == '/'){
					this.nextToken();
					String s;
					if (this.ttype == TT_NUMBER){
						s = (int) lab1+"/"+(int) this.nval;
						this.nextToken();
					}else throw new DotException(this, "number");
					if ((char) this.ttype == ']'){
						this.ttype=TT_FLOW;
						this.sval = s;
					}
					else throw new DotException(this, "]");
				}else throw new DotException(this);
			}
			else if (this.ttype==TT_WORD && this.sval.equalsIgnoreCase("color")){
				this.nextToken();
				String color = "";
				if ((char) this.ttype == '=') this.nextToken();
				else throw new DotException(this, "=");
				if (this.ttype == TT_WORD) color = this.sval;
				else throw new DotException(this, "color");
				this.nextToken();
				if ((char) this.ttype == ']'){
					this.ttype = TT_COLOR;
					this.sval = color;
				}
				else throw new DotException(this, "]");
			}
			else throw new DotException(this);
		}
		else throw new DotException(this, "> or -");
		return this.ttype;
	}
}



class DotException extends Exception{
	private static final long serialVersionUID = -1415527266178177223L;
	DotParser p;
	String expected;
	
	

	public DotException(DotParser p){
		this.p=p;
	}
	
	
	/**
	 * @param p 
	 * @param expected cha�ne attendue
	 */
	public DotException(DotParser p, String expected){
		this.p=p;
		this.expected = expected;
	}
	
	public String toString(){
		String s = new String("Parse error line "+ p.lineno() + "\n");
		s = s + "unexpected ' " + p + "' \n";
		if (!(expected==null || expected == "")) 
			s = s + expected + " expected ";
		return s;
	}
}         



